#include <iostream>
#include <cstdlib>
#include <string>
#include <fstream>
using namespace std;

#include <boost/program_options.hpp>
namespace bpo = boost::program_options;


#include "hhvsimple.hpp"

// ====================================================

const string inFileDefault = "image.pgm";
const string outFileDefault = "image.h5";

const string varNameDefault = "data";

string inFile( "no input" );
string outFile( "no output" );
string varName;


// =====================================================

void ReadCommandLine( int ac, char* av[] ) {

  try {
    bpo::options_description desc( "Allowed options" );

    desc.add_options()
      ("help", "Produce help message")
      ("name", bpo::value<string>(&varName)->default_value(varNameDefault), "Name of dataset in HDF5 file" )
      ;

    bpo::options_description hidden( "Hidden, positional options");
    hidden.add_options()
      ("input", bpo::value<string>(&inFile), "Name of the input file")
      ("output", bpo::value<string>(&outFile), "Name of the output file" )
      ;

    bpo::positional_options_description posOpt;
    posOpt.add( "input", 1 );
    posOpt.add( "output", 2 );

    bpo::options_description cmdLineOpts;
    cmdLineOpts.add(desc).add(hidden);

    bpo::variables_map vm;
    bpo::store( bpo::command_line_parser( ac, av ).options(cmdLineOpts).positional(posOpt).run(), vm );
    bpo::notify( vm );

    if( vm.count( "help" ) ) {
      cout << "pgm2h5 [options] <input file> <output file>" << endl;
      cout << desc << endl;
      exit( EXIT_SUCCESS );
    }
  }

  catch( exception& e ) {
    cerr << "Error: " << e.what() << endl;
    exit( EXIT_FAILURE );
  }
  catch( ... ) {
    cerr << "Unknown exception" << endl;
    exit( EXIT_FAILURE );
  }
  
}


// ==============================

int main( int argc, char *argv[] ) {

  SciGPU::HHV::HHVolumeSimple<long,2> imageVals;

  cout << "PGM to HDF5 convertor" << endl;
  
  ReadCommandLine( argc, argv );

 
  // ---------------------------
  // Parse through the file

  ifstream pgmFile( inFile.c_str() );

  string line;
  getline( pgmFile, line );

  // Check the file type
  if( line != "P2" ) {
    cerr << "Not a PGM file!" << endl;
    exit( EXIT_FAILURE );
  }

  // Advance over comments
  while( pgmFile.peek() == '#' ) {
    getline( pgmFile, line );
  }

  // Get dimensions
  size_t xPix, yPix;
  pgmFile >> xPix >> yPix;
  cout << "Dimensions are " << xPix << "x" << yPix << endl;

  // Get maximum pixel value
  long maxVal;
  pgmFile >> maxVal;
  cout << "Maximum value is " << maxVal << endl;

  
  // Allocate main array
  SciGPU::HHV::DimensionObject<2> imageSize;
  imageSize[0] = xPix;
  imageSize[1] = yPix;
  imageVals.Allocate( imageSize );

  // Read in data
  for( unsigned int iy=0; iy<yPix; iy++ ) {
    for( unsigned int ix=0; ix<xPix; ix++ ) {
      // Skip comments
      while( pgmFile.peek() == '#' ) {
        getline( pgmFile, line );
      } 
      pgmFile >> imageVals(ix,iy);
    }
  }
  imageVals.Send();

  // Write out the HDF5 file
  imageVals.WriteHDF5( outFile, varName );

  return( EXIT_SUCCESS );
}
